package linestrategy

import (
	"codejy/analysis"
	"codejy/analysis/lineanalysis"
	"codejy/globalfunc"
	"codejy/store"
	"codejy/structdef"
	"codejy/utils"
	"fmt"
	"strings"
)

// 定义函数和属性调用策略 ,多级调用
type UniteCallChaiAssignmentStrategy struct {
}

// 注册策略
func init() {
	RegisterStrategy(&UniteCallChaiAssignmentStrategy{})
}

// 判断是否是函数调用
func (f *UniteCallChaiAssignmentStrategy) getId() int {
	return lineanalysis.UniteCallChainAssignment
}

func (f *UniteCallChaiAssignmentStrategy) Execute(threadStore *structdef.ThreadStore) {
	content := threadStore.Code.LineContent
	//截取第一个=号的位置
	index := strings.Index(content, "=")
	//获取=号前面的变量名称
	variableName := content[:index]
	//获取=号后面的内容
	expression := content[index+1:]

	value := UniteCallChaiExecute(threadStore, expression)
	//判断变量点是否>=1,那么就是多级赋值 ,包括this.xx.xx,global.xx.xx ,xx.xx
	maps, str := utils.FuncBracketsReplace(variableName)
	if strings.Count(str, ".") >= 1 {
		//多级赋值
		UniteAssignment(threadStore, str, value, maps)
	} else {
		//存储变量
		var variableType = globalfunc.ExecuteFunc("CodeAnalysis", threadStore, value).(int)
		//将计算结果赋值给变量
		store.ModifyVariable(threadStore, structdef.NewVarDefinitionValue(variableName, value, variableType))

	}
}

// 多级赋值
func UniteAssignment(threadStore *structdef.ThreadStore, variableName, value string, replace map[string]string) {
	//按照.号分割
	split := strings.Split(variableName, ".")
	length := len(split) - 1
	var value1 string
	for i := 0; i < length; i++ {
		code := split[i]
		var skip = i
		//替换回去
		code = utils.FuncBracketsReplaceBack(replace, code)
		//如果开头是global,那么就将下一个拼接
		if strings.HasPrefix(code, "global") {
			code2 := utils.FuncBracketsReplaceBack(replace, split[i+1])
			code = code + "." + code2
			value1 = globalfunc.ExecuteFunc("AssignmentStrategyMode", threadStore, code).(string)
			skip = i + 1
		} else {
			value1 = globalfunc.ExecuteFunc("AssignmentStrategyMode", threadStore, code).(string)
		}
		//判断是最后一个元素
		if i == length-1 {
			break
		}

		if skip+1 < length {
			if value1 == "" {
				var errorStr = fmt.Sprintf("调用链中第%d个元素调用错误,因为返回值为空,请检查调用链的返回值是否正确,错误行代码:%s,错误代码为:%s", i, value, code)
				panic(errorStr)
			}
			//判断返回值是否是实例地址
			if !analysis.IsInstanceAddress(value1) {
				var errorStr = fmt.Sprintf("调用链中第%d个元素调用错误,因为返回值不是实例,请检查调用链的返回值是否正确,错误行代码:%s,错误代码为:%s", i, value, code)
				panic(errorStr)
			}
		}

		if skip == i {
			//将值和下一个元素拼接,给下一个
			if i+1 < length {
				value1 = value1 + "." + split[i+1]
				split[i+1] = value1
			}
		}
		i = skip
	}

	variableName = split[length] //获取最后一个元素,属性名称
	//设置属性值
	var variableType = globalfunc.ExecuteFunc("CodeAnalysis", threadStore, value).(int)
	store.SetInstanceProp(threadStore, value1, structdef.NewVarDefinitionValue(variableName, value, variableType))
}
